#include <sstream>
#include <cctype>

#include <iostream> /*DEBUG*/

#include "cargador_alumnos.h"
#include "funciones_string.h"

CargadorAlumnos::CargadorAlumnos(std::string path){

	this->archivo = new std::ifstream();
	this->archivo->open(path.c_str());
	if(! this->archivo->is_open()){
		throw std::ios_base::failure("El archivo no pudo ser abierto");
	}

	this->listaAlumnos = 0;
}

CargadorAlumnos::~CargadorAlumnos(){
	this->archivo->close();
	delete this->archivo;
}

Lista<Alumno*>* CargadorAlumnos::getListaAlumnos(){
	if(this->listaAlumnos != 0){
		return this->listaAlumnos;
	}

	this->listaAlumnos = new Lista<Alumno*>;

	this->cargarAlumnos();

	return this->listaAlumnos;
}

void CargadorAlumnos::cargarAlumnos(){
	std::string linea;

	while(getline(*(this->archivo), linea)){
		if(Alumno* nuevoAlumno = this->generarAlumno(linea)){
			this->listaAlumnos->agregar(nuevoAlumno);
		}
	}
}

Alumno* CargadorAlumnos::generarAlumno(std::string linea){

	Alumno *nuevoAlumno = new Alumno;
	std::istringstream lineaStream(linea);
	char comma;

	/**
	* Lectura del padron.
	*/
	int padron;
	if(! (lineaStream >> padron)){
		delete nuevoAlumno;
		return 0;
	}
	if(padron < 75000 || padron > 94000){
		delete nuevoAlumno;
		return 0;
	}

	/**
	* Lectura de una comma.
	*/
	if(! (lineaStream >> comma)){
		delete nuevoAlumno;
		return 0;
	}
	if(comma != ','){
		delete nuevoAlumno;
		return 0;
	}

	/**
	* Lecuta del sexo.
	*/
	char sexo;
	if(! (lineaStream >> sexo)){
		delete nuevoAlumno;
		return 0;
	}
	sexo = tolower(sexo);
	if(sexo != 'f' && sexo != 'm'){
		delete nuevoAlumno;
		return 0;
	}

	/**
	* Lectura de una comma.
	*/
	if(! (lineaStream >> comma)){
		delete nuevoAlumno;
		return 0;
	}
	if(comma != ','){
		delete nuevoAlumno;
		return 0;
	}

	/**
	* Lectura de la edad.
	*/
	int edad;
	if(! (lineaStream >> edad)){
		delete nuevoAlumno;
		return 0;
	}
	if(edad < 19 || edad > 70){
		delete nuevoAlumno;
		return 0;
	}

	/**
	* Lectura de una comma.
	*/
	if(! (lineaStream >> comma)){
		delete nuevoAlumno;
		return 0;
	}
	if(comma != ','){
		delete nuevoAlumno;
		return 0;
	}

	/**
	* Lectura del codigo de la carrera.
	*/
	int codigo;
	if(! (lineaStream >> codigo)){
		delete nuevoAlumno;
		return 0;
	}
	if(codigo != 9 && codigo != 10){
		delete nuevoAlumno;
		return 0;
	}

	/**
	* Lectura de una comma.
	*/
	if(! (lineaStream >> comma)){
		delete nuevoAlumno;
		return 0;
	}
	if(comma != ','){
		delete nuevoAlumno;
		return 0;
	}

	/**
	* Lectura del año de ingreso.
	*/
	int anio;
	if(! (lineaStream >> anio)){
		delete nuevoAlumno;
		return 0;
	}
	if(anio < 2000 || anio > 2008){
		delete nuevoAlumno;
		return 0;
	}

	/**
	* Lectura de una comma.
	*/
	if(! (lineaStream >> comma)){
		delete nuevoAlumno;
		return 0;
	}
	if(comma != ','){
		delete nuevoAlumno;
		return 0;
	}

	/**
	* Lectura de las materias aprobadas.
	*/
	int aprobadas;
	if(! (lineaStream >> aprobadas)){
		delete nuevoAlumno;
		return 0;
	}
	if(aprobadas < 1 || aprobadas > 10){
		delete nuevoAlumno;
		return 0;
	}

	/**
	* Lectura de una comma.
	*/
	if(! (lineaStream >> comma)){
		delete nuevoAlumno;
		return 0;
	}
	if(comma != ','){
		delete nuevoAlumno;
		return 0;
	}

	/**
	* Lectura de las materias desaprobadas.
	*/
	int desaprobadas;
	if(! (lineaStream >> desaprobadas)){
		delete nuevoAlumno;
		return 0;
	}
	if(desaprobadas < 1 || desaprobadas > 10){
		delete nuevoAlumno;
		return 0;
	}

	/**
	* Lectura de una comma.
	*/
	if(! (lineaStream >> comma)){
		delete nuevoAlumno;
		return 0;
	}
	if(comma != ','){
		delete nuevoAlumno;
		return 0;
	}

	/**
	* Lectura de si trabaja o no.
	*/
	std::string trabaja;
	char tmp;
	if(! (lineaStream >> tmp)){
		delete nuevoAlumno;
		return 0;
	}
	trabaja += tmp;
	if(! (lineaStream >> tmp)){
		delete nuevoAlumno;
		return 0;
	}
	trabaja += tmp;
	trabaja = lowerCase(trabaja);
	if(trabaja != "si" && trabaja != "no"){
		delete nuevoAlumno;
		return 0;
	}


	/**
	* Lectura de una comma.
	*/
	if(! (lineaStream >> comma)){
		delete nuevoAlumno;
		return 0;
	}
	if(comma != ','){
		delete nuevoAlumno;
		return 0;
	}

	/**
	* Lectura del promedio.
	*/
	float promedio;
	if(! (lineaStream >> promedio)){
		delete nuevoAlumno;
		return 0;
	}
	if(promedio < 0 || promedio > 10){
		delete nuevoAlumno;
		return 0;
	}

	/**
	* Lectura de una comma.
	*/
	if(! (lineaStream >> comma)){
		delete nuevoAlumno;
		return 0;
	}
	if(comma != ','){
		delete nuevoAlumno;
		return 0;
	}

	/**
	* Lectura de las horas de estudio semanales.
	*/
	int horasDeEstudio;
	if(! (lineaStream >> horasDeEstudio)){
		delete nuevoAlumno;
		return 0;
	}
	if(horasDeEstudio < 0 || horasDeEstudio > 60){
		delete nuevoAlumno;
		return 0;
	}

	/**
	* Ingreso de los datos.
	*/
	nuevoAlumno->setPromedioMayorACuatro(promedio > 4);
	nuevoAlumno->setEsHombre(sexo == 'm');
	nuevoAlumno->setMayorDeVeinticuatro(edad > 24);
	nuevoAlumno->setTrabaja(trabaja == "si");
	nuevoAlumno->setEstudiaSeisHorasSemanales(horasDeEstudio >= 6);

	return nuevoAlumno;

}

